後端好朋友 Express middleware


Posted by Christy on 2022-01-11

本文為 [BE201] 後端 Express 學習筆記,主要紀錄學習過程,裡面包含 express Middleware 介紹

零、內容摘要

1. 可以把 middleware 看成是中間商,就是幫忙處理行為的函式,並用 next() 交接給下一個 middleware。舉例來說,我要到某地旅遊,我把旅遊行程、交通、住宿分別外包給三個不同的中間商,而我從交通 → 行程 → 住宿都有人幫我處理好了,我只負責旅行,這中間的箭頭就是 next()

2. 常用的 middleware

a. Request body 有話要說,解析 Request 必備:body-parser

b. Session middleware,處理登入登出機制

c. connect-flash,處理錯誤訊息;提到把東西放在 locals 讓其他人也可以用

3. 基本用法:

a. 找到官方說明文件,然後下載

b. 在 index.js 引入使用

c. 找範例把程式碼拿進來

d. 在 index.js 新增路由,哪個網址可以讀哪些內容等等

e. controller 新增拿到資料以後的行動

f. views 處理畫面

一、什麼是 middleware?

是一個中間件,簡單來說就是幫忙處理行為的函式,利用 next() 把行動交給下一個函式:

fn A → next() → fn B …

  • 在 express 預設沒有能夠解析 req body 的內容如 POST、DELETE 這些 methods,也沒有 sessioin 管理機制,這些都要靠 middleware 完成

  • 在 express 裡有內建的是「可以拿到網址列的 query string」

二、解析 Request 必備:body-parser

必用,不然拿不到 req body 裡面的資料

body-parser

註:在新版的 body-parser 有自動幫你寫好,所以用 express.json() 其實就是在用 body-parser,因此新版來說,就用 express.json() 就好。可以參考 W17_直播檢討 Q7。

a. $ npm install body-parser

b. "Express/Connect top-level generic" 找範例

c. contetn type 兩個都拿進來,都會用到

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

// parse application/json
app.use(bodyParser.json())

d. 在 index.js 新增一個路由處理

app.post('/todos', todoController.newTodo)

e. views 的畫面 addTodo.ejs

<h1>Add Todo</h1>
<form method="POST" action="/todos">
  Content: <input type="text" name="content" />
  <input type="submit" />
</form>

f. 在 controller 新增一個 newTodo method

newTodo: (req, res) => {
  // 這裡的 req.body.content 就是上面 views input 裡面的 name
  const content = req.body.content
  res.end(content)
}

三、負責管理 Session 的 Session middleware

express-session

a. $ npm install express-session

b. 在 index.js 引入 const session = require('express-session')

c. 使用 session

// index.js
app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true,
  // 老師的範例沒有下面這一行,所以我無法登入
  // cookie: { secure: true }
}))

d. .get() 讀取畫面 & .post() 寫入登入行為

// index.js

app.get('/login', (req, res) => {
  res.render('login')
})

app.post('/login', (req, res) => {
  if (req.body.password === 'abc') {
    req.session.isLogin = true
    res.redirect('/')
  } else {
    res.redirect('/login')
  }
})

app.get('/logout', (req, res) => {
  req.session.isLogin = false
  res.redirect('/')
})

e. 在 controller 的 addTodo 新增登入

// controller > todo.js

addTodo: (req, res) => {
  res.render('addTodo', {
    isLogin: req.session.isLogin
  })
},

f. views > addTodo.ejs

// addTodo.ejs

<h1>Add Todo</h1>

<% if(isLogin) { %>
  Hello, user! <a href="/logout">logout</a>
<% } else { %>
  Wanna login?
<% } %>

<form method="POST" action="/todos">
  Content: <input type="text" name="content" />
  <input type="submit" />
</form>

g. login.ejs

// login.ejs

<h1>Login</h1>
<form method="POST" action="/login">
  password: <input type="password" name="password" />
  <input type="submit" />
</form>

四、connect-flash

1. 介紹 flash 這個 lib 怎麼用

2. 把東西放在 locals 讓其他人也可以用views 可以用任何來自 local 的東西,記得要用 res.locals,不是 req 喔。

a. connect-flash,安裝 $ npm install connect-flash

b. 在 index.js 引入 const flash = require('connect-flash')

c. 在 index.js 使用 app.use(flash())

d. 在登入裡面使用 flash: req.flash('errorMessage', 'invalid password') 兩個參數,前面錯誤訊息,後面訊息內容

app.get('/login', (req, res) => {
  res.render('login', {
    errorMessage: req.flash('errorMessage')
  })
})

app.post('/login', (req, res) => {
  if (req.body.password === 'abc') {
    req.session.isLogin = true
    res.redirect('/')
  } else {
    req.flash('errorMessage', 'invalid password')
    res.redirect('/login')
  }
})

e. 寫一個模板來給大家使用

app.use((req, res, next) => {
  res.locals.isLogin = req.session.isLogin
  res.locals.errorMessage = req.flash('errorMessage')
  next()
})

上面的 errorMessage: req.flash('errorMessage') 就不用了

views 可以用任何來自 local 的東西,記得要用 res.locals,不是 req 喔。










Related Posts

淺談 Markdown 格式

淺談 Markdown 格式

比較 innerText, textContent, innerHTML

比較 innerText, textContent, innerHTML

演習課 WEEK14 (部屬)

演習課 WEEK14 (部屬)


Comments